// Copyright 2008-2010 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================

#ifndef OMAHA_CORE_GOOGLE_UPDATE_CORE_H_
#define OMAHA_CORE_GOOGLE_UPDATE_CORE_H_

#include <windows.h>
#include <atlbase.h>
#include <atlcom.h>
#include <atlstr.h>
#include "base/atlregmapex.h"
#include "base/preprocessor_fun.h"
#include "base/synchronized.h"
#include "omaha/common/const_goopdate.h"
#include "omaha/goopdate/com_proxy.h"
#include "omaha/goopdate/elevation_moniker_resource.h"
#include "omaha/goopdate/non_localized_resource.h"

// Generated by MIDL in the "BUILD_MODE.OBJ_ROOT + SETTINGS.SUBDIR".
#include "goopdate/omaha3_idl.h"

namespace omaha {

class ATL_NO_VTABLE GoogleUpdateCoreBase
    : public CComObjectRootEx<CComMultiThreadModel>,
      public IGoogleUpdateCore,
      public StdMarshalInfo {
 public:
  GoogleUpdateCoreBase();
  virtual ~GoogleUpdateCoreBase();

  BEGIN_COM_MAP(GoogleUpdateCoreBase)
    COM_INTERFACE_ENTRY(IGoogleUpdateCore)
    COM_INTERFACE_ENTRY(IStdMarshalInfo)
  END_COM_MAP()

  // Launches a command line elevated.
  STDMETHOD(LaunchCmdElevated)(const WCHAR* app_guid,
                               const WCHAR* cmd_id,
                               DWORD caller_proc_id,
                               ULONG_PTR* proc_handle);
 private:
  // If the COM caller has permissions for process proc_id, opens and returns
  // the process handle.
  static HRESULT OpenCallerProcessHandle(DWORD proc_id, HANDLE* proc_handle);

  friend class GoogleUpdateCoreTest;

  DISALLOW_COPY_AND_ASSIGN(GoogleUpdateCoreBase);
};

template <bool is_service>
class ATL_NO_VTABLE GoogleUpdateCore
    : public GoogleUpdateCoreBase,
      public CComCoClass<GoogleUpdateCore<is_service> > {
 public:
  GoogleUpdateCore() {}
  virtual ~GoogleUpdateCore() {}

  DECLARE_NOT_AGGREGATABLE(GoogleUpdateCore)
  DECLARE_REGISTRY_RESOURCEID_EX(is_service ? IDR_LOCAL_SERVICE_RGS :
                                              IDR_LOCAL_SERVER_ELEVATION_RGS)

  BEGIN_REGISTRY_MAP()
    REGMAP_ENTRY(_T("PROGID"), is_service ? kProgIDGoogleUpdateCoreService :
                                            kProgIDGoogleUpdateCoreMachine)
    REGMAP_ENTRY(_T("VERSION"), _T("1"))
    REGMAP_ENTRY(_T("NAME"), _T("GoogleUpdateCoreClass"))
    REGMAP_ENTRY(_T("DESCRIPTION"), _T("Google Update Core Class"))
    REGMAP_UUID(_T("CLSID"), is_service ?
                             __uuidof(GoogleUpdateCoreClass) :
                             __uuidof(GoogleUpdateCoreMachineClass))
    REGMAP_ENTRY(L"ICONRESID", PP_STRINGIZE(IDI_ELEVATION_MONIKER_ICON))
    REGMAP_ENTRY(L"STRINGRESID",
                 PP_STRINGIZE(IDS_ELEVATION_MONIKER_DISPLAYNAME))
    REGMAP_MODULE2(L"MODULE", kOmahaOnDemandFileName)
  END_REGISTRY_MAP()

 private:
  DISALLOW_COPY_AND_ASSIGN(GoogleUpdateCore);
};

typedef GoogleUpdateCore<false> GoogleUpdateCoreMachine;
typedef GoogleUpdateCore<true> GoogleUpdateCoreService;

}  // namespace omaha

#endif  // OMAHA_CORE_GOOGLE_UPDATE_CORE_H_
